﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Threading;
using System.IO;
using System.Xml.Linq;
using System.Xml;
using System.Windows.Threading;
using System.Windows.Browser;
using System.Windows.Media.Imaging;
namespace et_test
{
    public partial class MainPage : UserControl
    {

        #region 变量

        int time = 0;

        DateTime begin;

        DateTime create;

        string examid;

        string categoryid;

        int index = 0;

        List<question> questions;

        DispatcherTimer checkBeginTimer;
        // 异常信息
        string _exception = "";
        // SynchronizationContext - 同步上下文管理类
        SynchronizationContext _syncContext;

        #endregion

        public MainPage()
        {
            try
            {
                questions = new List<question>();
                checkBeginTimer = new DispatcherTimer();
                examid = App.Current.Host.InitParams["examid"];
                categoryid = App.Current.Host.InitParams["categoryid"];

                //examid = "150";
                //categoryid = "1";
                string _url = string.Format("http://{0}/tools/ajax.aspx?t=getExamInfo&examid={1}&cid={2}", App.Current.Host.Source.AbsoluteUri.Split('/')[2], examid, categoryid);
                //string _url = string.Format("http://{0}/tools/ajax.aspx?t=getExamInfo&examid={1}&cid={2}", "localhost:3647", examid, categoryid);
                GetXML(_url);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "\r\n" + ex.StackTrace);
            }

            InitializeComponent();
            checkBeginTimer.Interval = new TimeSpan(0, 0, 0, 1, 0);
            checkBeginTimer.Tick += (s, e) =>{
                checkTime();
            };
        }

        private void checkTime()
        {
            if (time != 0 && begin != null)
            {
                create = create.AddSeconds(1);
                TimeSpan ts = begin.AddMinutes(time) - create;
                if (ts.TotalMinutes > 0 )
                {
                    timeText.Text = string.Format("{0}:{1}:{2}", ts.Hours, ts.Minutes, ts.Seconds);
                }
                else
                {
                    checkBeginTimer.Stop();
                    Submit();
                }
            }

        }

        #region request
        void GetXML(string url)
        {
            // SynchronizationContext.Current - 当前线程的同步上下文
            _syncContext = SynchronizationContext.Current;
            /*

             * HttpWebRequest - 对指定的 URI 发出请求

             *     HttpWebRequest.Create(uri) - 初始化一个 WebRequest

             *     HttpWebRequest.BeginGetResponse(AsyncCallback callback, Object state) - 开始对指定 URI 资源做异步请求

             *         AsyncCallback callback - System.AsyncCallback 委托。异步操作完成时调用的回调方法

             *         Object state - 包含此异步请求的对象。即相应的 HttpWebRequest 对象

             *     HttpWebRequest.Abort() - 取消该异步请求

             *     HttpWebRequest.Accept - HTTP 头的 Accept  部分

             *     HttpWebRequest.ContentType - HTTP 头的 ContentType 部分

             *     HttpWebRequest.Headers - HTTP 头的 key/value 对集合

             *     HttpWebRequest.Method - HTTP 方法（只支持GET和POST）

             *     HttpWebRequest.RequestUri - 所请求的 URI

             *     HttpWebRequest.HaveResponse - 是否接收到了指定 URI 的响应

             *     HttpWebRequest.AllowReadStreamBuffering - 是否对从 Internet 资源接收的数据做缓冲处理。默认值为true，将数据缓存在客户端内存中，以便随时被应用程序读取

             */
            HttpWebRequest request = WebRequest.Create(
                new Uri(url, UriKind.Absolute)) as HttpWebRequest;
            request.Method = "GET";
            request.BeginGetResponse(new AsyncCallback(ResponseCallback), request);

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="result">IAsyncResult.AsyncState - AsyncCallback 传过来的对象</param>
        private void ResponseCallback(IAsyncResult result)
        {
            HttpWebRequest request = result.AsyncState as HttpWebRequest;
            WebResponse response = null;
            try
            {
                // HttpWebRequest.EndGetResponse(IAsyncResult) - 结束对指定 URI 资源做异步请求
                //     返回值为 WebResponse 对象
                response = request.EndGetResponse(result) as HttpWebResponse;
            }
            catch (Exception ex)
            {
                _exception = ex.ToString();
            }
            // SynchronizationContext.Post(SendOrPostCallback d, Object state) - 将异步消息发送到该同步上下文中
            //     SendOrPostCallback d - System.Threading.SendOrPostCallback 委托
            //     Object state - 需要传递的参数
            _syncContext.Post(GetResponse, response);
        }

        /// <summary>
        /// HttpWebResponse - 对指定的 URI 做出响应
        /// GetResponseStream() - 获取响应的数据流
        /// </summary>
        /// <param name="state"></param>
        private void GetResponse(object state)
        {
            HttpWebResponse response = state as HttpWebResponse;
            if (response != null)
            {
                Stream responseStream = response.GetResponseStream();
                using (StreamReader sr = new StreamReader(responseStream))
                {
                    string xml = sr.ReadToEnd();
                    getTestInfo(xml);
                }
            }
            else
            {
                MessageBox.Show(_exception);
            }

        }

        void SetXML(string url)
        {
            // SynchronizationContext.Current - 当前线程的同步上下文
            _syncContext = SynchronizationContext.Current;
            /*

             * HttpWebRequest - 对指定的 URI 发出请求

             *     HttpWebRequest.Create(uri) - 初始化一个 WebRequest

             *     HttpWebRequest.BeginGetResponse(AsyncCallback callback, Object state) - 开始对指定 URI 资源做异步请求

             *         AsyncCallback callback - System.AsyncCallback 委托。异步操作完成时调用的回调方法

             *         Object state - 包含此异步请求的对象。即相应的 HttpWebRequest 对象

             *     HttpWebRequest.Abort() - 取消该异步请求

             *     HttpWebRequest.Accept - HTTP 头的 Accept  部分

             *     HttpWebRequest.ContentType - HTTP 头的 ContentType 部分

             *     HttpWebRequest.Headers - HTTP 头的 key/value 对集合

             *     HttpWebRequest.Method - HTTP 方法（只支持GET和POST）

             *     HttpWebRequest.RequestUri - 所请求的 URI

             *     HttpWebRequest.HaveResponse - 是否接收到了指定 URI 的响应

             *     HttpWebRequest.AllowReadStreamBuffering - 是否对从 Internet 资源接收的数据做缓冲处理。默认值为true，将数据缓存在客户端内存中，以便随时被应用程序读取

             */
            HttpWebRequest request = WebRequest.Create(
                new Uri(url, UriKind.Absolute)) as HttpWebRequest;
            request.Method = "GET";
            request.BeginGetResponse(new AsyncCallback(ResponseCallback2), request);

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="result">IAsyncResult.AsyncState - AsyncCallback 传过来的对象</param>
        private void ResponseCallback2(IAsyncResult result)
        {
            HttpWebRequest request = result.AsyncState as HttpWebRequest;
            WebResponse response = null;
            try
            {
                // HttpWebRequest.EndGetResponse(IAsyncResult) - 结束对指定 URI 资源做异步请求
                //     返回值为 WebResponse 对象
                response = request.EndGetResponse(result) as HttpWebResponse;
            }
            catch (Exception ex)
            {
                _exception = ex.ToString();
            }
            // SynchronizationContext.Post(SendOrPostCallback d, Object state) - 将异步消息发送到该同步上下文中
            //     SendOrPostCallback d - System.Threading.SendOrPostCallback 委托
            //     Object state - 需要传递的参数
            _syncContext.Post(GetResponse2, response);
        }

        /// <summary>
        /// HttpWebResponse - 对指定的 URI 做出响应
        /// GetResponseStream() - 获取响应的数据流
        /// </summary>
        /// <param name="state"></param>
        private void GetResponse2(object state)
        {
            HttpWebResponse response = state as HttpWebResponse;
            if (response != null)
            {
                Stream responseStream = response.GetResponseStream();
                using (StreamReader sr = new StreamReader(responseStream))
                {
                    string xml = sr.ReadToEnd();
                    AfterSet(xml);
                }
            }
            else
            {
                MessageBox.Show(_exception);
            }

        }

        #endregion

        private void getTestInfo(string xml)
        {
            try
            {
                this.questions.Clear();
                Byte[] b = System.Text.UTF8Encoding.UTF8.GetBytes(xml);
                XDocument xele = XDocument.Load(System.Xml.XmlReader.Create(new MemoryStream(b)));
                XElement sur = (from item in xele.Descendants("Data") select item).First();
                testText.Text = sur.Attribute(XName.Get("examtype")).Value;
                time = int.Parse(sur.Attribute(XName.Get("t")).Value);
                begin = DateTime.Parse(sur.Attribute(XName.Get("st")).Value);
                create = DateTime.Parse(sur.Attribute(XName.Get("ct")).Value);
                var partNos = from item in sur.Descendants("Info") select item;
                foreach (XElement ele in partNos)
                {
                    question que = new question();
                    que.Id = int.Parse(ele.Element(XName.Get("ID")).Value);
                    que.Title = ele.Element(XName.Get("Title")).Value;
                    que.TypeID = int.Parse(ele.Element(XName.Get("TypeID")).Value);
                    que.Type = ele.Element(XName.Get("Type")).Value;
                    que.CourseName = ele.Element(XName.Get("CourseName")).Value;
                    que.Score = int.Parse(ele.Element(XName.Get("Score")).Value);
                    que.Description = ele.Element(XName.Get("Description")).Value;
                    que.KnowledgePoint = ele.Element(XName.Get("KnowledgePoint")).Value;
                    que.ImgUrl = ele.Element(XName.Get("ImgUrl")).Value;
                    que.SoundUrl = ele.Element(XName.Get("SoundUrl")).Value;
                    que.Finalscore = que.Score;
                    var childNos = from item in ele.Element(XName.Get("Options")).Descendants("OptionInfo") select item;
                    foreach (XElement childele in childNos)
                    {
                        option opt = new option();
                        opt.ID = int.Parse(childele.Element(XName.Get("ID")).Value);
                        opt.SerialNumber = int.Parse(childele.Element(XName.Get("SerialNumber")).Value);
                        opt.Title = childele.Element(XName.Get("Title")).Value;
                        opt.IsCorrect = childele.Element(XName.Get("IsCorrect")).Value == "0"? false:true;
                        que.Options.Add(opt);
                    }
                    questions.Add(que);
                }

                index = 0;
                checkBeginTimer.Start();
                checkTime();
                pageText.Text = (index + 1).ToString();
                ShowQuestion(index);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "\r\n" + ex.StackTrace);
            }


        }

        private void ShowQuestion(int index)
        {
            if (questions.Count <= 0 || questions.Count< index + 1) return;
            checkSP.Children.Clear();
            pBtn.IsEnabled = index ==0? false:true;
            nBtn.IsEnabled = index == questions.Count - 1 ? false : true;
            question question = questions[index];
            typeText.Text = question.Type;
            nameText.Text = (index + 1).ToString()  +  ". " +  question.Title;
            string[] alphabet = new string[]{" ", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};
            if (question.TypeID == 2 || question.TypeID == 3 )
            {
                //客观题
                foreach (option op in question.Options)
                {
                    CheckBox cb = new CheckBox() { Name = alphabet[op.SerialNumber], Margin = new Thickness(2, 0, 5, 5), Padding = new Thickness(4, -2, 0, 0), FontSize = 13 };
                    cb.Content = alphabet[op.SerialNumber] + ". " + op.Title;
                    if (question.Answer.Contains(alphabet[op.SerialNumber]))
                    {
                        cb.IsChecked = true;
                    }
                    checkSP.Children.Add(cb);
                }
                if (question.ImgUrl != "")
                {
                    image.Source = new BitmapImage(new Uri(question.ImgUrl, UriKind.Absolute));
                }
                else
                {
                    image.Source = null; 
                }
            }
            else
            {
                //主观题
                if (question.TypeID == 4)
                {
                    TextBox tb = new TextBox() { Name = "tb", MinWidth = 200, Width = 600, HorizontalAlignment = System.Windows.HorizontalAlignment.Left,Margin = new Thickness(2,0,5,5) };
                    tb.Text = question.Answer;
                    checkSP.Children.Add(tb);
                }
                else
                {
                    TextBox tb = new TextBox() { Name = "tb", MinWidth = 200, Width = 600, Height = 200, TextWrapping = TextWrapping.Wrap, AcceptsReturn = true, HorizontalAlignment = System.Windows.HorizontalAlignment.Left, VerticalScrollBarVisibility = ScrollBarVisibility.Visible, Margin = new Thickness(2, 0, 5, 5) };
                    tb.Text = question.Answer;
                    checkSP.Children.Add(tb);
                }
                if (question.ImgUrl != "")
                {
                    image.Source = new BitmapImage(new Uri(question.ImgUrl));
                }
                else
                {
                    image.Source = null;
                }
            }
        }

        private void Save()
        { 
            question question = questions[index];
            if (question != null)
            {
                string answer = "";

                question.Finalscore = question.Score;

                if (question.TypeID == 2 || question.TypeID == 3)
                {
                    for (int i = 0; i < checkSP.Children.Count; i++)
                    {
                        CheckBox ele = checkSP.Children[i] as CheckBox;
                        if ((bool)ele.IsChecked)
                        {
                            if (!question.Options[i].IsCorrect)
                            {
                                question.Finalscore = 0;
                            }
                            answer = answer + "," + (ele as CheckBox).Name;
                        }
                        else
                        {
                            if (question.Options[i].IsCorrect)
                            {
                                question.Finalscore = 0;
                            }
                        }
                    }
                    if (answer == "")
                    {
                        question.Finalscore = 0;
                        question.Answer = "";
                    }
                    else
                    {
                        question.Answer = answer.Substring(1);
                    }
                    
                    
                }
                else
                {
                    question.Answer = (checkSP.Children[0] as TextBox).Text;
                }
            }
        }

        private void Submit()
        {
            int s = 0;
            string answer = "";
            string subjectivequestionAnswer = "";
            foreach (question que in questions)
            {
                if (que.TypeID == 2 || que.TypeID == 3)
                {
                    s = s + que.Finalscore;
                    answer = answer + "$$" + (que.Answer == "" ? " " : que.Answer);
                }
                else if (que.TypeID == 4 || que.TypeID == 5)
                {
                    subjectivequestionAnswer = subjectivequestionAnswer + "$$" + (que.Answer == "" ? " " : que.Answer);
                }
            }
            if (answer.Contains("$$"))
            {
                answer = answer.Substring(2);
            }
            if (subjectivequestionAnswer.Contains("$$"))
            {
                subjectivequestionAnswer = subjectivequestionAnswer.Substring(2);
            }
            sText.Text = "你的客观题考试成绩为：" + s.ToString() + "分";
            string url = string.Format("http://{0}/tools/ajax.aspx?t=setTestInfo&answers={1}&score={2}&examid={3}&cid={4}&subjectivequestionAnswer={5}", App.Current.Host.Source.AbsoluteUri.Split('/')[2], answer, s, examid, categoryid, subjectivequestionAnswer);
            //string url = string.Format("http://{0}/tools/ajax.aspx?t=setTestInfo&answers={1}&score={2}&examid={3}&cid={4}&subjectivequestionAnswer={5}", "localhost:3647", answer, s, examid, categoryid, subjectivequestionAnswer);
            SetXML(url);
            
        }

        private void AfterSet(string xml)
        {
            Byte[] b = System.Text.UTF8Encoding.UTF8.GetBytes(xml);
            XDocument xele = XDocument.Load(System.Xml.XmlReader.Create(new MemoryStream(b)));
            XElement sur = (from item in xele.Descendants("result") select item).First();
            if (sur.Value != "-1")
            {
                last.Visibility = System.Windows.Visibility.Visible;

                DispatcherTimer timer = new DispatcherTimer();
                int timeCount = 0;
                timer.Interval = TimeSpan.FromMilliseconds(500);
                timer.Tick += (s, e) =>
                    {
                        if (timeCount++ >= 2 )
                        {
                            timer.Stop();
                            if (HtmlPage.Window.Confirm("进入调查问卷吗？"))
                            {
                                this.Content = new Survey(int.Parse(examid), int.Parse(categoryid));
                            }
                        }
                    };
                timer.Start();
            }
            else
            {
                MessageBox.Show("保存失败！");
            }

        }

        private void pBtn_Click(object sender, RoutedEventArgs e)
        {
            Save();
            index --;
            pageText.Text = (index + 1).ToString();
            ShowQuestion(index);
        }

        private void nBtn_Click(object sender, RoutedEventArgs e)
        {
            Save();
            index++;
            pageText.Text = (index + 1).ToString();
            ShowQuestion(index);
        }

        private void closeBtn_Click(object sender, RoutedEventArgs e)
        {
            if (HtmlPage.Window.Confirm("您确定关闭窗口吗？"))
            {
                HtmlPage.Window.Invoke("CloseWindow", "");
            }
        }

        private void goBtn_Click(object sender, RoutedEventArgs e)
        {
            Save();
            if (pageText.Text.Trim() == "") return;
            try
            {
                int page = int.Parse(pageText.Text);
                if (questions != null && questions.Count >= page)
                {
                    index = page - 1;
                    ShowQuestion(index);
                }
            }
            catch
            {
                pageText.Text = "";
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Save();
            Confirm confirm = new Confirm();
            confirm.Show();
            confirm.Closed += (s, ex) =>
            {
                if ((bool)confirm.DialogResult)
                {
                    Submit();
                }
            };
        }

        private void surveyBtn_Click(object sender, RoutedEventArgs e)
        {
            this.Content = new Survey(int.Parse(examid), int.Parse(categoryid));
        }


    }
}
